# -*- coding: utf-8 -*-
#    Copyright 2005 Spike^ekipS <spikeekips@gmail.com>
#
#       This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

"""
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/84317

Thanks to David Perry.
"""

import threading, gc
import copy

import logging
import func
from thread__ import __default__

logger = __default__.logger

class Thread :

	pool = dict()
	pool_size = None

	def __init__ (self, pool_size) :
		self.pool_size = pool_size

	def getThreadCount (self) :
		return len(self.pool)

	def insert (self, cmd, args) :
		if len(self.pool) >= self.pool_size :
			return False

		# get uid
		__uid = func.get_unique_id()
		__child = FutureThread(__uid, self.pool, cmd, args)
		self.pool[__uid] = __child
		__child.start()

		gc.collect()

		return True

class FutureThread :

	def __init__ (self, uid, pool, cmd, param) :
		# Constructor
		self.__uid = uid
		self.__pool = pool
		self.cmd = cmd
		self.param = param

		self.__done = False
		self.__result = None
		self.__status = "working"

		self.__C = threading.Condition()   # Notify on this Condition when result is ready

	def start (self) :
		try :
			self.__T = \
				threading.Thread(target = self.Wrapper, args = (self.cmd, self.param))
			self.__T.setName("FThread")
			self.__T.start()
		except :
			raise

	def __repr__ (self) :
		return "<FThread at " + hex(id(self)) + ":" + self.__status + ">"

	def __call__ (self) :
		self.__C.acquire()
		while not self.__done :
			self.__C.wait()

		self.__C.release()
		# We deepcopy __result to prevent accidental tampering with it.
		a = copy.deepcopy(self.__result)
		return a

	def Wrapper (self, cmd, param) :
		# Run the actual function, and let us housekeep around it
		self.__C.acquire()
		try :
			self.__result = cmd(*param)
		except :
			self.__result = "Exception raised within FThread"
		else :
			logger.debug("thread done, %s" % self.param)

		self.__done = True
		self.__status = `self.__result`
		self.__C.notify()
		self.__C.release()

		# remove this thread child from thread pool
		if self.__pool.has_key(self.__uid) :
			del self.__pool[self.__uid]
		else :
			del self # destroy itself.

		logger.debug("Current thread number is %d" % len(self.__pool))

"""
Description
-----------


ChangeLog
---------


Usage
-----


"""

__author__ =  "Spike^ekipS <spikeekips@gmail.com>"
__version__=  "0.1"
__nonsense__ = ""

__file__ = "futurethread.py"


